package com.amigo.online.provider.user.util;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

import org.apache.log4j.Logger;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.ClientGlobal;
import org.csource.fastdfs.StorageClient1;
import org.csource.fastdfs.StorageServer;
import org.csource.fastdfs.TrackerClient;
import org.csource.fastdfs.TrackerServer;
import org.springframework.stereotype.Component;

/**
 * <code>FastDFSClient.java</code>
 * <p>
 * 功能:FastDFS分布式文件系统操作客户端 .
 *
 * <p>
 * Copyright 南京阿觅谷 2018 All right reserved.
 *
 * @author LILONG 时间 2018年6月21日 上午11:00:54
 * @version 1.0 </br>
 * 最后修改人 无
 */

@Component
public class FastDFSClient {

    private static StorageClient1 storageClient1 = null;

    private static Logger logger = Logger.getLogger(FastDFSClient.class);

    public static StorageClient1 getStorageClient1() throws Exception {
        String url = "fdfs/fdfs_client.conf";
        logger.info("=== CONF_FILENAME:" + url);
        ClientGlobal.init(url);
        TrackerClient trackerClient = new TrackerClient(ClientGlobal.g_tracker_group);
        TrackerServer trackerServer = trackerClient.getConnection();
        if (trackerServer == null) {
            logger.error("getConnection return null");
        }
        StorageServer storageServer = trackerClient.getStoreStorage(trackerServer);
        if (storageServer == null) {
            logger.error("getStoreStorage return null");
        }
        return new StorageClient1(trackerServer, storageServer);
    }

    public static String uploadFile(byte[] fileContent, String extName) throws Exception {
        return uploadFile(fileContent, extName, null);
    }

    public static String uploadFile(byte[] fileContent, String extName, NameValuePair[] metas) throws Exception {
        StorageClient1 storageClient1 = null;
        ConnectionPool pool = ConnectionPool.getConnectionPool();
        storageClient1 = pool.checkout(10);
        String result = null;
        try {
            result = storageClient1.upload_file1(fileContent, extName, metas);
            pool.checkin(storageClient1);
        } catch (IOException e) {
            // 如果出现了IO异常应该销毁此连接
            pool.drop(storageClient1);
            logger.error("上传文件IO异常");
        } catch (Exception e) {
            pool.drop(storageClient1);
            logger.error("上传文件异常");
        }
        return result;
    }

    /**
     * @param file     文件
     * @param filePath 文件名
     * @return 返回Null则为失败
     */
    public static String uploadFile(File file, String filePath) {
        FileInputStream fis = null;
        StorageClient1 storageClient1 = null;
        ConnectionPool pool = ConnectionPool.getConnectionPool();
        storageClient1 = pool.checkout(10);
        String fileid = null;
        NameValuePair[] meta_list = null; // new NameValuePair[0];
        try {
            fis = new FileInputStream(file);
            byte[] file_buff = null;
            if (fis != null) {
                int len = fis.available();
                logger.info("当前文件大小:" + len);
                file_buff = new byte[len];
                fis.read(file_buff);
            }
            fileid = storageClient1.upload_file1(file_buff, null, meta_list);
            pool.checkin(storageClient1);
            logger.info("当前文件名:" + fileid);
            return fileid;
        } catch (Exception ex) {
            logger.error("文件上传失败！");
            pool.drop(storageClient1);
            return null;
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    logger.error("关闭IO流失败!");
                }
            }
        }
    }

    /**
     * 根据组名和远程文件名来删除一个文件
     *
     * @param groupName 例如 "group1" 如果不指定该值，默认为group1
     * @param fileName  例如"M00/00/00/wKgxgk5HbLvfP86RAAAAChd9X1Y736.jpg"
     * @return 0为成功，非0为失败，具体为错误代码
     */
    public static int deleteFile(String groupName, String fileName) {
        try {
            int result = storageClient1.delete_file(groupName == null ? "group1" : groupName, fileName);
            return result;
        } catch (Exception ex) {
            logger.error(ex);
            return -1;
        }
    }

    /**
     * 根据fileId来删除一个文件（我们现在用的就是这样的方式，上传文件时直接将fileId保存在了数据库中）
     *
     * @param fileId file_id源码中的解释file_id the file id(including group name and
     *               filename);例如 group1/M00/00/00/ooYBAFM6MpmAHM91AAAEgdpiRC0012.xml
     * @return 0为成功，非0为失败，具体为错误代码
     */
    public static int deleteFile(String fileId) {
        try {
            int result = storageClient1.delete_file1(fileId);
            return result;
        } catch (Exception ex) {
            logger.error(ex);
            return -1;
        }
    }

    /**
     * 修改一个已经存在的文件
     *
     * @param oldFileId 原来旧文件的fileId, file_id源码中的解释file_id the file id(including group
     *                  name and filename);例如
     *                  group1/M00/00/00/ooYBAFM6MpmAHM91AAAEgdpiRC0012.xml
     * @param file      新文件
     * @param filePath  新文件路径
     * @return 返回空则为失败
     */
    public static String modifyFile(String oldFileId, File file, String filePath) {
        String fileid = null;
        try {
            // 先上传
            fileid = uploadFile(file, filePath);
            if (fileid == null) {
                return null;
            }
            // 再删除
            int delResult = deleteFile(oldFileId);
            if (delResult != 0) {
                return null;
            }
        } catch (Exception ex) {
            logger.error(ex);
            return null;
        }
        return fileid;
    }

    /**
     * 文件下载
     *
     * @param fileId
     * @return 返回一个流
     */
    public static InputStream downloadFile(String fileId) {
        try {
            byte[] bytes = storageClient1.download_file1(fileId);
            InputStream inputStream = new ByteArrayInputStream(bytes);
            return inputStream;
        } catch (Exception ex) {
            logger.error(ex);
            return null;
        }
    }

}
